package com.cykj.filters;

import com.alibaba.fastjson.JSON;
import com.cykj.dto.ResponseDTO;
import com.cykj.util.JwtUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.List;

import java.util.concurrent.TimeUnit;

/**
 * Project:jx2503fs
 * Package:com.cykj.filters
 *
 * @Description:
 * @Author:其一
 * @CreateTime: 2025-07-24-16-23
 */
@Component
public class LoginFilter implements GlobalFilter {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 设置白名单
        String[] urlWhite ={"/user/login","/user/reg","/code"};
        // 访问地址是否在白名单内，是就放行，不是就要进一步做判断
        String url = exchange.getRequest().getURI().getPath();
        for (String s : urlWhite) {
            if(s.equals(url)){
                return chain.filter(exchange);
            }
        }
        // 获取请求头里面的X-Token ==》如果没有或者过期就提示，否则就放行
        List<String> strings = exchange.getRequest().getHeaders().get("X-Token");
        String token = "";
        if (strings !=null && !strings.isEmpty()){
            token = strings.get(0);
        }
        // 判断token是否存在且不为""，如果不存在肯定直接返回告诉他token不存在请登录，否则接着判断token是否在有效期，如果无效测提示用户token不存在或已过期，请重新登录
        if(token ==null || token ==""){
            ServerHttpResponse response = exchange.getResponse();
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            response.getHeaders().add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
            ResponseDTO responseDTO =ResponseDTO.error(401,"用户未登录，请登录");
            return response.writeWith(Mono.just(response.bufferFactory().wrap(JSON.toJSONString(responseDTO).getBytes())));
        }

        String redisKey = "Token:login:" + token;
        if (redisTemplate.hasKey(redisKey)) {
            redisTemplate.expire(redisKey, 5, TimeUnit.MINUTES);
        }

        if(JwtUtils.isTokenExpired(token)){
            ServerHttpResponse response = exchange.getResponse();
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            response.getHeaders().add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
            ResponseDTO responseDTO = new ResponseDTO();
            responseDTO.error(401,"登录已过期，请重新登录");
            return response.writeWith(Mono.just(response.bufferFactory().wrap(JSON.toJSONString(responseDTO).getBytes())));
        }

        return chain.filter(exchange);
    }
}
